<template>
  <div class="file-upload">
    <div
      class="file-upload-container"
      @click.prevent="triggerUpload"
      v-bind="$attrs"
    >
      <!-- 根据它的状态显示相应的效果 -->
      <slot v-if="fileStatus === 'loading'" name="loading">
        <button class="btn btn-primary">正在上传...</button>
      </slot>
      <slot
        v-else-if="fileStatus === 'success'"
        name="uploaded"
        :uploadedData="uploadedData"
      >
        <button class="btn btn-primary">上传成功</button>
      </slot>
      <slot v-else name="default">
        <button class="btn btn-primary">点击上传</button>
      </slot>
    </div>
    <input
      type="file"
      class="file-input d-none"
      ref="fileInput"
      @change="handleFileChange"
    />
  </div>
</template>

<script lang="ts">
import { PropType, defineComponent, ref ,watch} from "vue";
import axios from "axios";
// 设置状态
// 准备上传 | 上传中 | 上传成功 | 上传失败
type UploadStatus = "ready" | "loading" | "success" | "error";
// 设置file类型
type CheckFunction = (file: File) => boolean;
export default defineComponent({
  props: {
    action: {
      type: String,
      required: true,
    },
    beforeUpload: {
      type: Function as PropType<CheckFunction>,
    },
    uploaded: {
      //有了这个属性就可以初始化一些 file 了
      type: Object,
    },
  },
  inheritAttrs: false,
  // 定义一个事件
  emits: ["file-uploaded", "file-uploaded-error"],
  setup(props, context) {
    const fileInput = ref<null | HTMLInputElement>(null);
    // 声明状态
    const uploadedData = ref(props.uploaded);
    // 获取状态
    const fileStatus = ref<UploadStatus>(props.uploaded ? "success" : "ready");
    
    // watch的第一个参数是响应式的，在这里只是一个普通对象用get方式直接返回一个值
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    watch(()=>props.uploaded,(newValue)=>{
      if(newValue){
        fileStatus.value = 'success'
        uploadedData.value = newValue
      }
    })
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    watch(()=>props.uploaded,(newValue)=>{
      
    })
    const triggerUpload = () => {
      if (fileInput.value) {
        fileInput.value.click(); //给input绑定一个单击事件
      }
    };
    // 添加方法 监听input的改变
    const handleFileChange = (e: Event) => {
      const currentTarget = e.target as HTMLInputElement;
      if (currentTarget.files) {
        fileStatus.value = "loading";
        const files = Array.from(currentTarget.files);
        // 是否满足用户自定义的需求
        if (props.beforeUpload) {
          const result = props.beforeUpload(files[0]);
          if (!result) {
            return;
          }
        }
        const formData = new FormData();
        formData.append("file", files[0]);
        axios
          .post(props.action, formData, {
            headers: {
              "Content-Type": "multipart/form-data",
            },
          })
          .then((resp) => {
            console.log(resp.data);
            fileStatus.value = "success";
            uploadedData.value = resp.data;
            // 成功的时候触发
            context.emit("file-uploaded", resp.data);
          })
          .catch((error) => {
            console.log(error);

            fileStatus.value = "error";
            // 失败的时候触发
            context.emit("file-uploaded-error", { error });
          })
          .finally(() => {
            //上传完毕设置成空值
            if (fileInput.value) {
              // 将上传文件的文本框设置为空
              fileInput.value.value = "";
            }
          });
      }
    };
    return {
      fileInput,
      triggerUpload,
      fileStatus,
      handleFileChange,
      uploadedData,
    };
  },
});
</script>

<style></style>
